/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * GJFrame.java
 *
 * Created on Mar 17, 2011, 7:48:24 PM
 */

package edu.pdx.cs.guavalib;

import edu.pdx.cs.guavadata.AppData;
import edu.pdx.cs.guavadata.GSeed;
import edu.pdx.cs.guavadata.Guava;
import edu.pdx.cs.guavadata.data.DMLType;
import edu.pdx.cs.guavadata.domain.Domain;
import edu.pdx.cs.guavadata.domain.UniqueIdentifier;
import edu.pdx.cs.guavadata.subclass.ControlType;
import edu.pdx.cs.guavadata.subclass.DataSet;
import edu.pdx.cs.guavadata.subclass.GSeedFrame;
import edu.pdx.cs.guavadata.subclass.GuavaForm;
import edu.pdx.cs.guavadata.subclass.GuavaLaunchBase;
import edu.pdx.cs.guavadata.subclass.LaunchType;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.apache.commons.lang3.StringUtils;

/**
 *
 * @author VuTran
 */
public class GJFrame extends javax.swing.JFrame implements GuavaForm {

    /** Creates new form GJFrame */
    public GJFrame() {
        this.guavaComponents = new ArrayList<Guava>();
        initComponents();
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(GJFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(GJFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(GJFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(GJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public GJFrame(UUID id, UUID fk, boolean bNew, GSeed gseed) {
        this();
        this.init(id, fk, bNew, gseed);
        
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        btnGJFrameOK = new javax.swing.JButton();
        btnGJFrameCancel = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        btnGJFrameOK.setText("OK");
        btnGJFrameOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnGJFrameOKActionPerformed(evt);
            }
        });

        btnGJFrameCancel.setText("Cancel");
        btnGJFrameCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnGJFrameCancelActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(310, Short.MAX_VALUE)
                .addComponent(btnGJFrameOK, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(btnGJFrameCancel)
                .addGap(16, 16, 16))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(302, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnGJFrameOK)
                    .addComponent(btnGJFrameCancel))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnGJFrameOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGJFrameOKActionPerformed
        try {
            save();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, e.toString());
        }
    }//GEN-LAST:event_btnGJFrameOKActionPerformed

    private void btnGJFrameCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGJFrameCancelActionPerformed
        try {
            cancel();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, e.getMessage());
        }
    }//GEN-LAST:event_btnGJFrameCancelActionPerformed


    /**
    * @param args the command line arguments
    
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new GJFrame().setVisible(true);
            }
        });
    }*/


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnGJFrameCancel;
    private javax.swing.JButton btnGJFrameOK;
    // End of variables declaration//GEN-END:variables

    List<Guava> guavaComponents;
    GSeed gseed;
    protected UUID thisID, thisFK;
    String gname;
    protected boolean bNew;
    protected int row;
    int dialogResult;

    public void init(UUID id, UUID fk, boolean bNew, GSeed gseed) {
        this.gseed = gseed;
        thisID = id;
        thisFK = fk;
        this.bNew = bNew;
        if (id.equals(fk)) {
            // We have single-launch situation
            row = AppData.fetchRowOrCreate(this.getGName(), id);
        } else if (bNew) {
            // we have a multiple-launch, "new object" situation
            row = AppData.createRow(this.getGName(), id, fk);
            AppData.commitRow(this.getGName(), id, DMLType.INSERT);
        } else {
            // We have mutiple-launch, "edit object" situation
            row = AppData.fetchRow(this.getGName(), id);
        }

        // Attach data
        for (Guava cc : getGComponents())
            cc.gBindFromDatabase(getGName(), row);
        DataSet ds = AppData.ds;
        try {
            // Test the GSeed - see if we need to make some action
            if (this.gseed == null) {
                // create new seed, then add the current form to the seed frames
                this.gseed = new GSeed(this.getClass().getName(), AppData.dbsource, AppData.dbcatalog);
                this.gseed.push(new GSeedFrame(this.id, this.gname));
            } else if (this.gseed.needToAdvance()) {
                // Action!

                // If the "need to advance" flag is set, then some automation is necessary
                // Use the current frame's information to find the appropriate launch mechanism
                GSeedFrame gsfTemp = this.gseed.peekAdvance();
                UUID next = this.gseed.nextId();

                // Loop through the gsfTemp controls list to find the right launcher
                Guava gTemp = this;
                for (String c : gsfTemp.controls)
                {
                    gTemp = gTemp.get(c);
                    if (gTemp == null)
                        throw new Exception("Could not find control path " + StringUtils.join(gsfTemp.controls.toArray(), "/") + " on form " + this.GName);
                }

                // gTemp is now the control that was used to launch the next form, or held the mark
                // Use gTemp's machinery to launch the next form or highlight the mark
                if (this.gseed.needToAdvance())
                {
                    if (!(gTemp instanceof GuavaLaunchBase))
                        throw new Exception("Control " + StringUtils.join(gsfTemp.controls.toArray(), "/") + " is not a launchable control.");
                    GuavaLaunchBase glb = (GuavaLaunchBase) gTemp;

                    // Set the control's internal ID to the correct value and launch
                    // Notice that the form is necessarily NOT a new object
                    glb.setObject(next);
                    glb.launchForm(next, gsfTemp.form, false);
                }
            } else {
                // Add the current form to the seed frames
                this.gseed.push(new GSeedFrame(this.id, this.gname));
            }
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    public void save() {
        for (Guava g : this.getGComponents()) {
            g.gBind(this.getGName(), row);
        }
        AppData.commitRow(getGName(), thisID, DMLType.UPDATE);
        this.gseed.pop();
        this.dialogResult = JOptionPane.OK_OPTION;
        //if (this.PersistSignal != null) this.PersistSignal(this, new PersistSignalEventArgs(true));
        this.dispose();
    }

    public void cancel() {
        if (this.thisID == this.thisFK) {
            // rejectChanges
        } else if (bNew) {
            AppData.commitRow(getGName(), this.thisID, DMLType.DELETE);
            //AppData.ds.getTable(gname).rejectChanges();
        } else {
            // reject changes
        }
        this.gseed.pop();
        this.dialogResult = JOptionPane.CANCEL_OPTION;
        // if (this.PersistSignal != null) this.PersistSignal(this, new PersistSignalEventArgs(false));
        this.dispose();
    }

    public void addGComponent(Guava g) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public LaunchType getLType() {
        return LaunchType.NA;
    }

    public ControlType getCType() {
        return ControlType.Entity;
    }

    public String getGText() {
        return this.getTitle();
    }

    public String getGName() {
        if (gname == null)
            return this.getName();
        return gname;
    }

    public void setGName(String GName) {
        gname = GName;
        return;
    }

    public Point getGLocation() {
        return this.getLocation();
    }

    public Dimension getGSize() {
        return this.getSize();
    }

    public List<Guava> getGComponents() {
        List<Guava> lg = new ArrayList<Guava>();

        for (Component c : this.getComponents())
            getGComponentRec(c, lg);
        for (Guava g : this.guavaComponents)
            lg.add(g);

        return lg;
    }

    public void getGComponentRec(Component c, List<Guava> lg) {
        if (c instanceof Guava) {
            lg.add((Guava) c);
        } else if (c instanceof Container) {
            for (Component com : ((Container) c).getComponents())
                getGComponentRec(com, lg);
        }
    }

    public UUID getID() {
        return this.thisID;
    }

    public void setID(UUID id) {
        this.thisID = id;
    }

    public void gBind(String table, int i) {
        return;
    }

    public void gBindFromDatabase(String table, int i) {
        return;
    }

    public String getGDefault() {
        return null;
    }

    public String getGToolTip() {
        return null;
    }

    public Domain getGDomain() {
        return new UniqueIdentifier();
    }

    public Guava get(String s) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public GSeed getGSeed() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void setGSeed(edu.pdx.cs.guavadata.GSeed gs) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
